package org.springblade.modules.digitalization.service.impl;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.*;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.google.common.collect.Lists;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.MurmurHash3;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springblade.common.enums.ChineseUnicode;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.oss.ArchiveMinioTemplate;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.digitalization.config.ArchiveConfiguration;
import org.springblade.modules.digitalization.contant.ConstantDigit;
import org.springblade.modules.digitalization.dto.*;
import org.springblade.modules.digitalization.entity.*;
import org.springblade.modules.digitalization.excel.A01ArchiveEntity;
import org.springblade.modules.digitalization.manager.DataExchangeCallback;
import org.springblade.modules.digitalization.manager.LogManager;
import org.springblade.modules.digitalization.mapper.ManageRsdamlMapper;
import org.springblade.modules.digitalization.mapper.UmsUserInfoMapper;
import org.springblade.modules.digitalization.service.*;
import org.springblade.modules.digitalization.utils.*;
import org.springblade.modules.digitalization.vo.CatalogItem;
import org.springblade.modules.digitalization.vo.DataExchangeVO;
import org.springblade.modules.digitalization.vo.UmsUserInfoVO;
import org.springblade.modules.digitalization.wrapper.UserDaRs;
import org.springblade.modules.digitalization.wrapper.UserInfoRs;
import org.springblade.modules.digitalization.wrapper.UserMenuRs;
import org.springblade.modules.system.entity.Dict;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.service.IDictService;
import org.springblade.modules.system.service.ITenantService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import java.io.*;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static org.springblade.modules.digitalization.utils.OfdUtils.*;

/**
 * 人员基础模型-JAVA 服务实现类
 *
 * @author RS
 * @since 2022-10-18
 */
@Service
@Slf4j
public class UmsUserInfoServiceImpl extends BaseServiceImpl<UmsUserInfoMapper, UmsUserInfoEntity> implements IUmsUserInfoService {

	@Autowired
	ArchiveConfiguration archiveConfiguration;
	@Autowired
	RestTemplate restTemplate;
	@Autowired
	IB01Service ib01Service;
	@Autowired
	IA01Service a01Service;
	@Autowired
	IA02Service a02Service;
	@Autowired
	IA57Service a57Service;
	@Autowired
	ITenantService iTenantService;
	@Autowired
	IDictService dictService;
	@Autowired
	IManageArchivesService manageArchivesService;

	@Autowired
	IManageRsdamlService manageRsdamlService;
	@Autowired
	ManageRsdamlMapper manageRsdamlMapper;
	@Autowired
	IManageRsdawjService manageRsdawjService;
	@Autowired
	IDigitPinyinService digitPinyinService;
	@Autowired
	private ArchiveMinioTemplate minioTemplate;

	@Autowired
	private LogManager logManager;
	@Autowired
	private ITenantService tenantService;
	private static Pattern pattern = Pattern.compile(String.format("^(%s){1,4}([0-9]{15}|[0-9]{18}|[0-9]{15,18}[X,x])(\\.zip)$",
		ChineseUnicode.getChineseRegx()));

	@Value("${blade.delTmpFile:true}")
	private Boolean deleteFile;

	@Override
	public IPage<UmsUserInfoVO> selectUmsUserInfoPage(IPage<UmsUserInfoVO> page, UmsUserInfoVO umsUserInfo) {
		return page.setRecords(baseMapper.selectUmsUserInfoPage(page, umsUserInfo));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void doReceiveAsync(MultipartFile file, String b0111) {
		B01Entity selectB01 = ib01Service.getOne(Wrappers.<B01Entity>lambdaQuery().eq(B01Entity::getB0111, b0111));
		//读取文件内容
		UserListener dictListener = new UserListener();
		try {
			EasyExcel.read(file.getInputStream(), A01A02Entity.class, dictListener).sheet().doRead();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//转换为b01
		List<A01A02Entity> upLoads = dictListener.getA01A02EntityList();
		for (A01A02Entity a01A02Entity : upLoads) {
			if (a01A02Entity.getResult()) {
				try {
					checkBaseZip(a01A02Entity, selectB01);
					//移动文件
					updateManageArchive(a01A02Entity, selectB01);
				} catch (ServiceException e) {
					a01A02Entity.setResult(false);
					a01A02Entity.setReason(e.getMessage());
					log.info(e.getMessage());
				}

			}
		}
	}


	@Transactional(rollbackFor = Exception.class)
	public void doReceiveAsyncCpp(MultipartFile file, String b0111) {
		B01Entity selectB01 = ib01Service.getOne(Wrappers.<B01Entity>lambdaQuery().eq(B01Entity::getB0111, b0111));
		//读取文件内容
		UserListener dictListener = new UserListener();
		try {
			EasyExcel.read(file.getInputStream(), A01A02Entity.class, dictListener).sheet().doRead();
		} catch (IOException e) {
			e.printStackTrace();
		}
		//转换为b01
		List<A01A02Entity> upLoads = dictListener.getA01A02EntityList();
		for (A01A02Entity a01A02Entity : upLoads) {
			if (a01A02Entity.getResult()) {
				try {
					checkBaseZip(a01A02Entity, selectB01);
					//移动文件
					updateManageArchive(a01A02Entity, selectB01);
				} catch (ServiceException e) {
					a01A02Entity.setResult(false);
					a01A02Entity.setReason(e.getMessage());
					log.info(e.getMessage());
				}

			}
		}
	}

	private static final String FILE_HASH_KEY_PREFIX = "file_hash:";

	private RedisTemplate<String, String> redisTemplate;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<A01ArchiveEntity> doImport(MultipartFile excel, String b0111) {

		B01Entity selectB01 = ib01Service.getOne(Wrappers.<B01Entity>lambdaQuery().eq(B01Entity::getB0111, b0111));
		//读取文件内容
		CommonDataListener<A01ArchiveEntity> dictListener = new CommonDataListener<A01ArchiveEntity>();
		try {
			EasyExcel.read(excel.getInputStream(), A01ArchiveEntity.class, dictListener).sheet().doRead();
		} catch (IOException e) {
			e.printStackTrace();
		}
		List<A01ArchiveEntity> data = dictListener.getData();
		List<A01ArchiveEntity> errordata = Lists.newArrayList();
		List<A01Entity> a01Entities = Lists.newArrayList();
		List<A02Entity> a02Entities = Lists.newArrayList();
		List<ManageArchivesEntity> archivesEntities = Lists.newArrayList();
		List<DigitPinyinEntity> pinyinEntities = Lists.newArrayList();
		if (Func.isEmpty(data)) {
			throw new ServiceException("数据为空，请核对文件内容");
		}
		for (int i = 0; i < data.size(); i++) {
			String a0000 = IdUtil.randomUUID();
			A01ArchiveEntity a01ArchiveEntity = data.get(i);
			if (Func.isBlank(a01ArchiveEntity.getA0101()) || Func.isBlank(a01ArchiveEntity.getA0184()) || Func.isBlank(a01ArchiveEntity.getA0221())) {
				throw new ServiceException("请核对文件内容或缺少字段");
			}
			try {
				UmsUserInfoEntity one = getOne(Wrappers.<UmsUserInfoEntity>lambdaQuery().eq(UmsUserInfoEntity::getA0184,
					a01ArchiveEntity.getA0184()));
				if (Func.isNotEmpty(one)) {
					throw new ServiceException("");
				}
			} catch (Exception e) {
				a01ArchiveEntity.setErrorMsg("身份证号已存在");
				errordata.add(a01ArchiveEntity);
				continue;
			}
			Dict rs_09 = dictService.getOne(Wrappers.<Dict>lambdaQuery().eq(Dict::getCode, "RS_09").eq(Dict::getDictValue,
				a01ArchiveEntity.getA0221()), false);
			if (Func.isNull(rs_09)) {
				a01ArchiveEntity.setErrorMsg("职级信息错误");
				errordata.add(a01ArchiveEntity);
				continue;
			}
			a01ArchiveEntity.setA0221(rs_09.getDictKey());
			A01Entity a01Entity = new A01Entity();
			try {
				String yyyyMMdd = StringUtils.replaceAll(a01ArchiveEntity.getA0107(), "-", "");
				a01Entity.setA0107(yyyyMMdd);
			} catch (Exception e) {
				a01ArchiveEntity.setErrorMsg("出生日期格式错误");
				errordata.add(a01ArchiveEntity);
				continue;
			}

			a01Entity.setA0195(b0111);
			a01Entity.setA0000(a0000);
			a01Entity.setTenantId(AuthUtil.getTenantId());
			BeanUtil.copy(a01ArchiveEntity, a01Entity);

			A02Entity a02Entity = new A02Entity();
			a02Entity.setA0000(a0000);
			a02Entity.setA0201a(selectB01.getB0104());
			a02Entity.setA0201b(b0111);
			a02Entity.setA0255("1");
			a02Entity.setA0279("1");
			a02Entity.setTenantId("000000");

			ManageArchivesEntity archivesEntity = new ManageArchivesEntity();
			archivesEntity.setA0000(a0000);
			archivesEntity.setB0111(selectB01.getB0111());
			archivesEntity.setArchiveId(IdUtil.randomUUID());
			a01Entities.add(a01Entity);
			a02Entities.add(a02Entity);
			archivesEntities.add(archivesEntity);


		}
		a01Service.saveBatch(a01Entities);
		a02Service.saveBatch(a02Entities);
		manageArchivesService.saveBatch(archivesEntities);
		for (A01Entity a01Entity : a01Entities) {
			DigitPinyinEntity digitPinyinEntity = digitPinyinService.getOne(Wrappers.<DigitPinyinEntity>lambdaQuery().eq(DigitPinyinEntity::getOrgId
				, a01Entity.getId()), false);
			if (Func.isEmpty(digitPinyinEntity)) {
				digitPinyinEntity = new DigitPinyinEntity();
				digitPinyinEntity.setOrgId(a01Entity.getId());
				digitPinyinEntity.setTableType("A01@A0101");
			}
			digitPinyinEntity.setSourceData(a01Entity.getA0101());
			digitPinyinEntity.setPinyin(PinyinUtil.getPinyin(a01Entity.getA0101(), "") + " " + PinyinUtil.getFirstLetter(a01Entity.getA0101(), ""));
			pinyinEntities.add(digitPinyinEntity);
		}
		digitPinyinService.saveBatch(pinyinEntities);

		a01Entities.forEach(item -> {
			logManager.doImport(item.getA0000(), LogManager.TYPE_A01, item);
		});
		return errordata;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean saveOneDa(UmsUserInfoEntity a01ArchiveEntity) {

		String a0000;
		if (a01ArchiveEntity.getA0000() != null) {
			a0000 = a01ArchiveEntity.getA0000();
		} else {
			a0000 = IdUtil.randomUUID();
		}

		// 新增数据检查身份是否重复
		if (a01ArchiveEntity.getId() == null && StringUtils.isNotBlank(a01ArchiveEntity.getA0184())) {
			try {
				UmsUserInfoEntity one = getOne(Wrappers.<UmsUserInfoEntity>lambdaQuery().eq(UmsUserInfoEntity::getA0101,
					a01ArchiveEntity.getA0101()).eq(UmsUserInfoEntity::getA0184, a01ArchiveEntity.getA0184()));
				if (Func.isNotEmpty(one)) {
					throw new ServiceException("相同姓名与身份证号的人员已存在");
				}
			} catch (Exception e) {
				throw new ServiceException(e.getMessage());
			}
		}

		a01ArchiveEntity.setA0000(a0000);

		A01Entity a01Entity = new A01Entity();

		BeanUtil.copy(a01ArchiveEntity, a01Entity);

		a01Entity.setA0107(a01ArchiveEntity.getA0107());

		a01Entity.setA0195(a01ArchiveEntity.getA0201b());
		a01Entity.setA0000(a0000);
		a01Entity.setTenantId(AuthUtil.getTenantId());
		A01Entity exitsA01 = a01Service.getByA0000(a0000);
		if (exitsA01 != null) {
			a01Entity.setId(exitsA01.getId());
		}

		A02Entity a02Entity = new A02Entity();
		a02Entity.setA0000(a0000);
		a02Entity.setA0201a(a01ArchiveEntity.getA0201a());
		a02Entity.setA0201b(a01ArchiveEntity.getA0201b());
		a02Entity.setA0255("1");
		a02Entity.setA0279("1");
		a02Entity.setTenantId(AuthUtil.getTenantId());

		ManageArchivesEntity archivesEntity = new ManageArchivesEntity();
		archivesEntity.setA0000(a0000);
		archivesEntity.setB0111(a01ArchiveEntity.getA0201b());
		archivesEntity.setArchiveId(IdUtil.randomUUID());
		a01ArchiveEntity.setArchiveId(archivesEntity.getArchiveId());


		DigitPinyinEntity digitPinyinEntity = digitPinyinService.getOne(Wrappers.<DigitPinyinEntity>lambdaQuery().eq(DigitPinyinEntity::getOrgId,
			a01Entity.getId()), false);
		if (Func.isEmpty(digitPinyinEntity)) {
			digitPinyinEntity = new DigitPinyinEntity();
			digitPinyinEntity.setOrgId(a01Entity.getId());
			digitPinyinEntity.setTableType("A01@A0101");
		}
		digitPinyinEntity.setSourceData(a01Entity.getA0101());
		digitPinyinEntity.setPinyin(PinyinUtil.getPinyin(a01Entity.getA0101(), "") + " " + PinyinUtil.getFirstLetter(a01Entity.getA0101(), ""));

		a01Service.saveOrUpdate(a01Entity);
		// 新增数据
		if (a01ArchiveEntity.getId() == null) {
			a02Service.save(a02Entity);
			manageArchivesService.save(archivesEntity);
			logManager.doAdd(a0000.trim(), LogManager.TYPE_A01, a01Entity);
		} else {
			logManager.doUpdate(a0000.trim(), LogManager.TYPE_A01, exitsA01, a01Entity);
		}
		digitPinyinService.saveOrUpdate(digitPinyinEntity);
		return true;
	}


	@Override
	public void doExchangeTask(DataExchangeVO dataExchangeVO, boolean enableHd, DataExchangeCallback callback) {

		dataExchangeVO.setStatus(ConstantDigit.DATA_EXCHANGE_STATUS_PROCESS);
		dataExchangeVO.setMessage("转换中");

		callback.handleUpdate(dataExchangeVO);

		UserInfoRs userInfoRs = a01Service.getUserInfoByArchiveId(dataExchangeVO.getA0000());

		UserDaRs userDaRs = new UserDaRs();
		userDaRs.setUserInfo(userInfoRs);

		File tempFolder = new File(archiveConfiguration.getGbPath() + File.separator + userInfoRs.getId());
		this.deleteFile(tempFolder);
		// 下载原始文件和高清文件到本地
		try {
			List<UserMenuRs> menuRsList = this.getAndDownMenuList(dataExchangeVO, userInfoRs, callback, dataExchangeVO.getDipUnit());
			userDaRs.setMenus(menuRsList);
		} catch (Exception e) {
			// 这里错误说明文件下载有问题，直接退出
			String errorMsg = "文件下载错误：" + e.getMessage();
			dataExchangeVO.setMessage(errorMsg);
			dataExchangeVO.setStatus(ConstantDigit.DATA_EXCHANGE_STATUS_ERROR);
			callback.handleUpdate(dataExchangeVO);
			log.error(errorMsg, e);
			return;
		}

		String message = "";

		Boolean isZipSuccess = null;
		Boolean isOfdSuccess = null;

		if (dataExchangeVO.getIsZip()) {
			// 创建国标ZIP文件
			try {
				this.createAndUploadGbZipFile(userInfoRs, enableHd, userDaRs, callback);
				dataExchangeVO.setZip(true);
				isZipSuccess = true;
			} catch (Exception e) {
				String errorMsg = "创建国标ZIP文件错误：" + e.getMessage();
				message += errorMsg + "\n";
				dataExchangeVO.setZip(false);
				callback.handleUpdate(dataExchangeVO);
				log.error(errorMsg, e);
				isZipSuccess = false;
			}
		}

		if (dataExchangeVO.getIsOfd()) {
			try {
				this.createAndUploadOfdFile(userInfoRs, enableHd, userDaRs, callback);
				dataExchangeVO.setOfd(true);
				isOfdSuccess = true;
			} catch (Exception e) {
				String errorMsg = "创建OFD文件错误：" + e.getMessage();
				message += errorMsg + "\n";
				dataExchangeVO.setOfd(false);
				callback.handleUpdate(dataExchangeVO);
				log.error(errorMsg, e);
				isOfdSuccess = false;
			}
		}

		if (StringUtils.isBlank(message)) {
			this.updateUserStatusToFinish(userInfoRs, isZipSuccess, isOfdSuccess);
			dataExchangeVO.setMessage("转换完成");
			dataExchangeVO.setStatus(ConstantDigit.DATA_EXCHANGE_STATUS_FINISH);
		} else {
			dataExchangeVO.setMessage(message);
			dataExchangeVO.setStatus(ConstantDigit.DATA_EXCHANGE_STATUS_ERROR);
		}
		this.deleteFile(tempFolder);
		callback.handleUpdate(dataExchangeVO);
	}

	private void updateUserStatusToFinish(UserInfoRs userInfoRs, Boolean isZip, Boolean isOfd) {

		log.info("update status 7 for user : {}", userInfoRs.getId());
		LambdaUpdateWrapper<A01Entity> objectLambdaQueryWrapper = new LambdaUpdateWrapper<A01Entity>();
		objectLambdaQueryWrapper.set(A01Entity::getStatus, 7);
		if (isZip != null) {
			objectLambdaQueryWrapper.set(A01Entity::getIsZip, isZip);
		}
		if (isOfd != null) {
			objectLambdaQueryWrapper.set(A01Entity::getIsOfd, isOfd);
		}

		objectLambdaQueryWrapper.eq(A01Entity::getA0000, userInfoRs.getId());
		objectLambdaQueryWrapper.eq(A01Entity::getIsDeleted, 0);
		objectLambdaQueryWrapper.eq(A01Entity::getStatus, 6);
		a01Service.update(objectLambdaQueryWrapper);

	}

	private void createAndUploadGbZipFile(UserInfoRs userInfoRs, boolean enableHd, UserDaRs userDaRs, DataExchangeCallback callback) {

		String userId = userInfoRs.getUserName() + userInfoRs.getIdCard();

		String zipFileName = String.format("%s/%s.zip", userInfoRs.getId(), userId);
		String zipFilePath = String.format("%s/%s", archiveConfiguration.getGbPath(), zipFileName);

		String formatXml = String.format("%s/%s/%s.xml", archiveConfiguration.getGbPath(), userInfoRs.getId(), userId);

		if (enableHd == false) {
			userDaRs.getMenus().forEach(menu -> {
				menu.setHdImgs(Lists.newArrayList());
			});
		}

		int imageCount = userDaRs.getMenus().stream().mapToInt(menu -> menu.getOrgImgs().size() + menu.getHdImgs().size()).sum();
		try {
			GbUtils.saveXmlByUser(userDaRs, formatXml);
		} catch (Exception e) {
			log.error("国标XML文件创建失败", e);
			throw new RuntimeException(e.getMessage());
		}

		String userLocalPath = archiveConfiguration.getGbPath() + File.separator + userInfoRs.getId();
		File folder = new File(userLocalPath);
		File zipFolder = folder.toPath().resolveSibling(userId).toFile();

		try {
			FileUtil.copyContent(folder, zipFolder, true);
			DaUtils.compressFolder(zipFolder.getPath(), zipFilePath);
			callback.addSuccessCount(imageCount);
		} catch (Exception e) {
			log.error("国标ZIP文件压缩错误", e);
			throw new RuntimeException("国标ZIP文件压缩错误：" + e.getMessage());
		}

		File zipFile = new File(zipFilePath);
		log.info("zipFilePath:{}", zipFilePath);
		try (InputStream bufferedGbInputStream = Files.newInputStream(zipFile.toPath())) {
			minioTemplate.uploadFile(bufferedGbInputStream, zipFileName);
		} catch (Exception e) {
			log.error("国标ZIP文件上传失败", e);
			throw new RuntimeException("国标ZIP文件上传失败：" + e.getMessage());
		} finally {
			callback.addSuccessCount(imageCount);
		}
		this.deleteFile(zipFolder);
	}

	private void createAndUploadOfdFile(UserInfoRs userInfoRs, boolean enableHd, UserDaRs userDaRs, DataExchangeCallback callback) throws IOException {

		String ofdFileName = String.format("%s/%s%s.ofd", userInfoRs.getId(), userInfoRs.getUserName(), userInfoRs.getIdCard());
		String ofdFilePath = String.format("%s/%s", archiveConfiguration.getGbPath(), ofdFileName);

		String dirName = IMG_HD;
		String path = archiveConfiguration.getGbPath() + File.separator + userInfoRs.getId();
		if (enableHd == false) {
			dirName = IMG_ORG;
			userDaRs.getMenus().forEach(menu -> {
				menu.setHdImgs(menu.getOrgImgs());
			});
		}
		int imageCount = userDaRs.getMenus().stream().mapToInt(menu -> menu.getOrgImgs().size() + (enableHd ? menu.getHdImgs().size() : 0)).sum();

		try {
			creaateOfdByImgs(path, dirName, userDaRs);
		} catch (Exception e) {
			log.error("创建OFD文件错误", e);
			throw new RuntimeException("创建OFD文件错误：" + e.getMessage());
		}

		SelectRsdamlRead selectRsdamlRead = new SelectRsdamlRead();
		selectRsdamlRead.setA0000(userInfoRs.getId());
		List<CatalogItem> catalogItems = manageRsdamlService.slectCatalogItem(selectRsdamlRead);

		try {
			OfdUtils.createMenu(path, userDaRs, catalogItems);
		} catch (Exception e) {
			log.error("创建OFD文件错误", e);
			throw new RuntimeException("创建OFD文件错误：" + e.getMessage());
		}
		callback.addSuccessCount(imageCount);

		File ofdFile = new File(ofdFilePath);
		log.info("ofdFilePath:{}", ofdFilePath);
		try (InputStream bufferedInputStream = Files.newInputStream(ofdFile.toPath())) {
			minioTemplate.uploadFile(bufferedInputStream, ofdFileName);
		} catch (Exception e) {
			log.error("Ofd文件上传错误", e);
			throw new RuntimeException("Ofd文件上传错误：" + e.getMessage());
		} finally {
			callback.addSuccessCount(imageCount);
		}
	}


	/**
	 * 下载原始图与高清图，并获取文件列表
	 *
	 * @param userInfoRs
	 * @return
	 */
	@SneakyThrows
	private List<UserMenuRs> getAndDownMenuList(DataExchangeVO dataExchangeVO, UserInfoRs userInfoRs, DataExchangeCallback callback,
												Integer imageUnit) {

		String orgPathStr = String.format("%s/图像数据/原始图像数据/", userInfoRs.getId());
		String hdPathStri = String.format("%s/图像数据/优化图像数据/", userInfoRs.getId());

		Path pathOrg = Paths.get(archiveConfiguration.getGbPath() + File.separator + orgPathStr);
		Path pathHd = Paths.get(archiveConfiguration.getGbPath() + File.separator + hdPathStri);

		if (!Files.exists(pathOrg)) {
			log.info("create pathOrg {}", pathOrg);
			Files.createDirectories(pathOrg);
			Files.createDirectories(pathHd);
		}

		List<UserMenuRs> menuRsList = manageRsdamlService.getMenusByA0000(userInfoRs.getId());


		int sum = menuRsList.stream().mapToInt(UserMenuRs::getPageNum).sum();
		// 处理高清图的话，数目加倍
		sum = sum + (dataExchangeVO.getEnableHd() ? sum : 0);

		int taskSteps = sum;
		//  n(下载) + n(zip) + n(zip上传) + n(ofd) + n(ofd上传)
		if (dataExchangeVO.getIsOfd()) {
			taskSteps += sum * 2;
		}

		if (dataExchangeVO.getIsZip()) {
			taskSteps += sum * 2;
		}

		callback.setTaskCount(taskSteps);

		for (UserMenuRs menuRs : menuRsList) {
			String createAtStr = "";
			if (StringUtils.isNotBlank(menuRs.getYear())) {
				createAtStr += menuRs.getYear();
			}
			if (StringUtils.isNotBlank(menuRs.getMonth())) {
				createAtStr += menuRs.getMonth();
			}
			if (StringUtils.isNotBlank(menuRs.getDay())) {
				createAtStr += menuRs.getDay();
			}
			menuRs.setCreateAtStr(createAtStr);
			List<String> orgs = menuRs.getOrgImgs().subList(0, menuRs.getPageNum());
			List<String> hds = menuRs.getHdImgs().subList(0, menuRs.getPageNum());
			for (int i = 0; i < menuRs.getPageNum(); i++) {
				String orgFileName = menuRs.getOrgImgs().get(i);
				String formattedNumber = String.format("%03d", i + 1);
				String targetName = GbUtils.getPreFix(menuRs.getClassNum(), menuRs.getIdNum(), formattedNumber);
				try {
					String localFileName = pathOrg.toAbsolutePath() + File.separator + targetName;
					minioTemplate.downloadObj(orgPathStr + orgFileName, localFileName);
					// 修改文件dpi
//					ImgUtils.changeDpi(localFileName, 300, imageUnit);
					orgs.set(i, targetName);
				} catch (Exception e) {
					String message = String.format("文件【%s-%s-p%s-%s】原始文件下载错误：%s，下载地址：%s", menuRs.getClassNum(), menuRs.getIdNum(), i + 1,
						menuRs.getCaiLiaoName(), e.getMessage(), orgPathStr + orgFileName);
					throw new RuntimeException(message);
				} finally {
					callback.addSuccessCount(1);
				}
				if (dataExchangeVO.getEnableHd()) {
					try {
						String localFileName = pathHd.toAbsolutePath() + File.separator + targetName;
						minioTemplate.downloadObj(hdPathStri + orgFileName, localFileName);
//						ImgUtils.changeDpi(localFileName, 300, imageUnit);
						hds.set(i, targetName);
					} catch (Exception e) {
						String message = String.format("文件【%s-%s-p%s-%s】高清文件下载错误：%s，下载地址：%s", menuRs.getClassNum(), menuRs.getIdNum(), i + 1,
							menuRs.getCaiLiaoName(), e.getMessage(), hdPathStri + orgFileName);
						throw new RuntimeException(message);
					} finally {
						callback.addSuccessCount(1);
					}
				}
			}
			menuRs.setOrgImgs(orgs);
			menuRs.setHdImgs(hds);
		}
		return menuRsList;
	}

	private void deleteFile(File file) {
		try {
			if (deleteFile) {
				boolean del = FileUtil.del(file);
				log.info("delete old file [{}]: {}", del, file.getAbsolutePath());
			} else {
				if (FileUtil.exist(file)) {
					FileUtil.move(file, new File(file.getAbsolutePath() + "_del"), true);
					log.info("move old file : {}", file.getAbsolutePath());
				} else {
					log.info("move old file cancel, no src file: {}", file.getAbsolutePath());
				}
			}
		} catch (Exception e) {
			log.info("delete/move file error: {}", file.getAbsolutePath());
			log.error(e.getMessage(), e);
		}
	}

	@Override
	public ResponseEntity<Resource> downData(HttpServletRequest request, String type, Long id) throws IOException {
		UserInfoRs byId = a01Service.getUserInfoBy(id);

		if (Func.isNotEmpty(byId)) {
			String filePathP = "";
			String fileName = byId.getUserName() + byId.getIdCard();
			if (type.equals("gb")) {
				filePathP = archiveConfiguration.getGbPath() + File.separator + fileName + ".zip";
			} else {
				filePathP = archiveConfiguration.getOfdPath() + File.separator + fileName + ".ofd";
			}

			// 解码文件名
			String filePath = URLDecoder.decode(filePathP, "UTF-8");
			// 获取图片文件路径
//			String filePath = filePathP +  File.separator + fileName;
			Path path = Paths.get(filePath);
			if (!Files.exists(path)) {
				return new ResponseEntity<>(HttpStatus.NOT_FOUND);
			}
			org.springframework.core.io.Resource resource = new UrlResource(path.toUri());
			String contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
			if (StringUtils.isBlank(contentType)) {
				contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
			}
			return ResponseEntity.ok().contentType(MediaType.parseMediaType(contentType)).body(resource);
		} else {
			throw new ServiceException("错误");
		}
	}


	/**
	 * 文件移动到update目录并且更新上传记录表
	 *
	 * @param a01A02Entity
	 */
	private void updateManageArchive(A01A02Entity a01A02Entity, B01Entity daB01) throws ServiceException {
		//判断文件存在
		String parent = FileUtil.getParent(archiveConfiguration.getUpdateZipPath() + a01A02Entity.getTrueMoveTmpPath(), 1);
		if (!FileUtil.exist(parent)) {
			FileUtil.mkdir(parent);
		}
		//判断文件是否已经被上传接收过
		//TODO: 优化接收项 变成移动
		File filePath = new File(archiveConfiguration.getUpdateZipPath() + a01A02Entity.getTrueMoveTmpPath());
		File orgFile = new File(archiveConfiguration.getReceiveZipPath() + File.separator + a01A02Entity.getZipFileName());
		if (FileUtil.exist(filePath)) {
			File file = new File(orgFile.getAbsolutePath() + "1");
			orgFile.renameTo(file);
		}
		orgFile.renameTo(filePath);
		//解压
		try {
			ZipUtil.unzip(archiveConfiguration.getUpdateZipPath() + a01A02Entity.getTrueMoveTmpPath(),
				archiveConfiguration.getArchivePath() + File.separator + a01A02Entity.getTenantName() + a01A02Entity.getTenantId(),
				CharsetUtil.CHARSET_GBK);
			String targetFilePath =
				archiveConfiguration.getArchivePath() + File.separator + a01A02Entity.getTenantName() + a01A02Entity.getTenantId() + File.separator + org.springblade.core.tool.utils.FileUtil.getNameWithoutExtension(a01A02Entity.getZipFileName());
			UserDaRs userDaRs = DaUtils.checkZipFileStructIsComplete(targetFilePath);

			//根据身份证查询出数据，先保证有数据主要是生成a0000
			A01Entity a01Entity = a01Service.getOne(Wrappers.<A01Entity>lambdaQuery().eq(A01Entity::getA0184, userDaRs.getUserInfo().getIdCard()),
				false);
			//保存人员信息
			if (Func.isNotEmpty(a01Entity)) {
				if (a01Entity.getTenantId() != a01A02Entity.getTenantId()) {
					throw new ServiceException("该人员已经在" + a01A02Entity.getTenantName() + "接收，请转出或者移除后再进行接收");
				}

			} else {
				a01Entity = new A01Entity();
				a01Entity.setA0184(userDaRs.getUserInfo().getIdCard());
				a01Entity.setA0000(IdUtil.randomUUID());
				a01Entity.setTenantId(a01A02Entity.getTenantId());
				//设置 创建单位 id
				a01Entity.setCreateDept(daB01.getId());
				// a01表设置租户id
			}
			UserInfoRs userInfoRs = userDaRs.getUserInfo();
			//民族更新
			if (Func.isNotBlank(userInfoRs.getMz())) {
				String mz = userInfoRs.getMz();
				if (!mz.contains("族") && !mz.equals("其他")) {
					Dict dict = new Dict();
					dict.setCode("GB3304");
					dict.setDictValue(mz);
					Dict one1 = dictService.getOne(Condition.getQueryWrapper(dict), false);
					if (Func.isNull(one1)) {
						throw new ServiceException("民族信息字典不存在:" + mz);
					} else {
						a01Entity.setA0117(one1.getDictKey());
					}
				}
			}
			//性别更新
			if (Func.isNotBlank(userInfoRs.getSex())) {
				Dict dict = new Dict();
				dict.setCode("GB2261");
				dict.setDictValue(userInfoRs.getSex());
				Dict one1 = dictService.getOne(Condition.getQueryWrapper(dict), false);
				if (Func.isNull(one1)) {
					throw new ServiceException("性别信息字典不存在:" + userInfoRs.getSex());
				} else {
					a01Entity.setA0104(one1.getDictKey());
				}
			}
			//旧的数据已经存在
			a01Entity.setA0101(userInfoRs.getUserName());
			a01Entity.setA0107(userInfoRs.getBirthDay());
			a01Entity.setA0195(a01A02Entity.getA0201B());
			a01Entity.setTenantId(a01A02Entity.getTenantId());
			a01Entity.setA01Status("1");

			A02Entity a02EntityExist =
				a02Service.getOne(Wrappers.<A02Entity>lambdaQuery().eq(A02Entity::getA0000, a01Entity.getA0000()).eq(A02Entity::getTenantId,
					a01A02Entity.getTenantId()), false);
			if (Func.isEmpty(a02EntityExist)) {
				a02EntityExist = new A02Entity();
				a02EntityExist.setA0000(a01Entity.getA0000());
				a01A02Entity.setTenantId(a01Entity.getTenantId());
				a02EntityExist.setA0255("1");//在职
				a02EntityExist.setA0279("1");//主职务
			}
			a02EntityExist.setA0201a(a01A02Entity.getA0201A());
			a02EntityExist.setA0201b(a01A02Entity.getA0201B());
			a02EntityExist.setCreateDept(daB01.getId());


			//更新档案信息 档案--目录--页 3个表

			ManageArchivesEntity archivesEntity =
				manageArchivesService.getOne(Wrappers.<ManageArchivesEntity>lambdaQuery().eq(ManageArchivesEntity::getA0000, a01Entity.getA0000()),
					false);
			if (Func.isEmpty(archivesEntity)) {
				archivesEntity = new ManageArchivesEntity();
				archivesEntity.setArchiveId(IdUtil.randomUUID());
			} else {
				if (!archivesEntity.getTenantId().equals(daB01.getTenantId()) && !a01Entity.getA01Status().equals("03")) {
					throw new ServiceException("其他单位已经存在该档案");
				}
			}
			archivesEntity.setA0000(a01Entity.getA0000());
			archivesEntity.setB0111(daB01.getB0111());
			archivesEntity.setTenantId(a01Entity.getTenantId());
			String localPath = a01A02Entity.getTenantName() + a01A02Entity.getTenantId() + File.separator + a01A02Entity.getZipFileName();
			archivesEntity.setLocalPath(localPath);
			archivesEntity.setArchiveState("02");
			archivesEntity.setStatus(DaUtils.E_ARCHIVE);
			archivesEntity.setCreateDept(daB01.getId());


			//
			manageRsdamlService.remove(Wrappers.<ManageRsdamlEntity>lambdaQuery().eq(ManageRsdamlEntity::getTenantId, daB01.getTenantId()).eq(ManageRsdamlEntity::getA0000, a01Entity.getA0000()));
			manageRsdawjService.remove(Wrappers.<ManageRsdawjEntity>lambdaQuery().eq(ManageRsdawjEntity::getTenantId, daB01.getTenantId()).eq(ManageRsdawjEntity::getA0000, a01Entity.getA0000()));

			List<UserMenuRs> menuRsList = userDaRs.getMenus();
			ManageArchivesEntity finalArchivesEntity = archivesEntity;
			List<ManageRsdawjEntity> rsdawjList = new ArrayList();
			List<ManageRsdamlEntity> rsdamlEntityList = menuRsList.stream().map(a -> {
				ManageRsdamlEntity manageRsdamlEntity = new ManageRsdamlEntity();
				manageRsdamlEntity.setRsdaml000(IdUtil.randomUUID());
				manageRsdamlEntity.setArchiveId(finalArchivesEntity.getArchiveId());
				manageRsdamlEntity.setA0000(finalArchivesEntity.getA0000());
				manageRsdamlEntity.setRsdaml002(a.getClassNum());
				manageRsdamlEntity.setClassSort(manageRsdamlService.getClassMap(a.getClassNum()));
				manageRsdamlEntity.setRsdaml003(Integer.valueOf(a.getIdNum()));
				manageRsdamlEntity.setRsdaml004(a.getCaiLiaoName());
				manageRsdamlEntity.setRsdaml005(Integer.valueOf(a.getPageNum()));

				manageRsdamlEntity.setTenantId(daB01.getTenantId());
				if (Func.isNotEmpty(a.getCreateAt())) {
					String date = DateUtil.format(a.getCreateAt(), "yyyy-MM-dd");
					String year = date.substring(0, date.indexOf("-"));
					String month = date.substring(date.indexOf("-") + 1, date.lastIndexOf("-"));
					String day = date.substring(date.lastIndexOf("-") + 1);
					manageRsdamlEntity.setRsdaml006(year);
					manageRsdamlEntity.setRsdaml007(month);
					manageRsdamlEntity.setRsdaml008(day);
				}
				for (int i = 0; i < Integer.valueOf(a.getPageNum()); i++) {
					List<String> orgImgs = a.getOrgImgs();
					List<String> hdImgs = a.getHdImgs();
					ManageRsdawjEntity rsdawj = new ManageRsdawjEntity();
					rsdawj.setA0000(finalArchivesEntity.getA0000());
					rsdawj.setRsdawj000(manageRsdamlEntity.getRsdaml000());
					rsdawj.setRsdawj001(String.valueOf(i + 1));
					rsdawj.setRsdawj003(orgImgs.get(i));
					rsdawj.setRsdawj004(hdImgs.get(i));
					String imgS =
						a01A02Entity.getTenantName() + a01A02Entity.getTenantId() + File.separator + a01A02Entity.getZipFileName().replace(".zip",
							"") + File.separator + DaUtils.IMG_DATA + File.separator;

					String orgMd5 =
						SecureUtil.md5(new File(archiveConfiguration.getArchivePath() + File.separator + imgS + DaUtils.NORMAL_IMG_DATA + File.separator + orgImgs.get(i)));
					String hdMd5 =
						SecureUtil.md5(new File(archiveConfiguration.getArchivePath() + File.separator + imgS + DaUtils.HIGH_IMG_DATA + File.separator + hdImgs.get(i)));
					rsdawj.setMd5(orgMd5);
					rsdawj.setHqMd5(hdMd5);
					rsdawj.setHqLocalPath(imgS + DaUtils.HIGH_IMG_DATA);
					rsdawj.setLocalPath(imgS + DaUtils.NORMAL_IMG_DATA);
					String deptId = AuthUtil.getDeptId();
					rsdawj.setCreateDept(StringUtils.isEmpty(deptId) ? null : Long.parseLong(deptId));
					rsdawj.setCreateUser(AuthUtil.getUserId());
					rsdawj.setCreateTime(new Date());
					rsdawj.setTenantId(daB01.getTenantId());
					rsdawj.setArchiveId(finalArchivesEntity.getArchiveId());
					rsdawj.setA0000(finalArchivesEntity.getA0000());
					rsdawjList.add(rsdawj);
				}
				return manageRsdamlEntity;
			}).collect(Collectors.toList());

			if (archiveConfiguration.getOss()) {
				Tenant tenant = tenantService.getByTenantId(daB01.getTenantId());
				File file =
					new File(archiveConfiguration.getArchivePath() + File.separator + a01A02Entity.getTenantName() + a01A02Entity.getTenantId() + File.separator + a01A02Entity.getZipFileName().replace(".zip", ""));
				minioTemplate.setTenantId(tenant.getTenantId());
				minioTemplate.uploadArchive(file);
				file.delete();
			}

			a01Service.saveOrUpdate(a01Entity);
			a02Service.saveOrUpdate(a02EntityExist);

			DigitPinyinEntity digitPinyinEntity = digitPinyinService.getOne(Wrappers.<DigitPinyinEntity>lambdaQuery().eq(DigitPinyinEntity::getOrgId
				, a01Entity.getId()), false);
			if (Func.isEmpty(digitPinyinEntity)) {
				digitPinyinEntity = new DigitPinyinEntity();
				digitPinyinEntity.setOrgId(a01Entity.getId());
				digitPinyinEntity.setTableType("A01@A0101");
			}
			digitPinyinEntity.setSourceData(a01Entity.getA0101());
			digitPinyinEntity.setPinyin(PinyinUtil.getPinyin(a01Entity.getA0101(), "") + " " + PinyinUtil.getFirstLetter(a01Entity.getA0101(), ""));


			digitPinyinService.saveOrUpdate(digitPinyinEntity);
			manageArchivesService.saveOrUpdate(archivesEntity);
			manageRsdawjService.saveBatch(rsdawjList);
			manageRsdamlService.saveBatch(rsdamlEntityList);
		} catch (Exception e) {
			filePath.renameTo(orgFile);
			throw new ServiceException(e.getMessage());
		}


	}

	private void checkBaseZip(A01A02Entity a01A02Entity, B01Entity b0111) throws ServiceException {
		String filePath = File.separator + a01A02Entity.getZipFileName();

		if (!FileUtil.exist(archiveConfiguration.getReceiveZipPath() + filePath)) {
			throw new ServiceException("文件包不存在:" + archiveConfiguration.getReceiveZipPath() + filePath);
		}
		B01Entity one = ib01Service.getOne(Wrappers.<B01Entity>lambdaQuery().eq(B01Entity::getB0111, a01A02Entity.getA0201B()));

		if (Func.isNull(one)) {
			throw new ServiceException("找不到对应的机构");
		}
		if (one.getTenantId().equals(b0111.getB0111())) {
			throw new ServiceException("找不到对应的机构");
		}
		//TODO: 这里是非租户模式
		if (Func.isBlank(b0111.getTenantId())) {
//		if (Func.isBlank(b0111.getTenantId()) || b0111.getTenantId().equals(BladeConstant.ADMIN_TENANT_ID)) {
			//未开启租户，记录原因并跳过
			throw new ServiceException(String.format("选择单位%s(%s)未开启租户", a01A02Entity.getA0201A(), a01A02Entity.getA0201B()));
		}
		A01Entity one1 =
			a01Service.getOne(Wrappers.<A01Entity>lambdaQuery().eq(A01Entity::getA0184, a01A02Entity.getA0184()).ne(A01Entity::getTenantId,
				b0111.getTenantId()), false);
		if (Func.isNotEmpty(one1)) {
			Tenant otherTenant = iTenantService.getByTenantId(one1.getTenantId());
			throw new ServiceException(String.format("已在其他单位:%s接收", otherTenant.getTenantName()));
		}
		a01A02Entity.setTenantId(one.getTenantId());
		a01A02Entity.setTenantName(one.getB0104());
		String updatePath =
			File.separator + a01A02Entity.getTenantName() + a01A02Entity.getTenantId() + File.separator + a01A02Entity.getZipFileName();
		a01A02Entity.setTrueMoveTmpPath(updatePath);
		Matcher matcher = pattern.matcher(a01A02Entity.getZipFileName()); //匹配输入字符串
		boolean isMatch = matcher.matches(); //判断是否匹配成功
		if (!isMatch) {
			throw new ServiceException("档案包名称错误");
		}
	}

	/**
	 * 审核
	 * 1. 保证目录中的都进行过扫描
	 * 2. 保证扫描中的都进行了高清处理
	 * 3. 修改a01中的状态位
	 *
	 * @param a01
	 * @return
	 */
	@Transactional
	@Override
	public String aduit(A01Entity a01) {
		String s = checkWj(a01, false);
		if (Func.isBlank(s)) {
			LambdaUpdateWrapper<A01Entity> objectLambdaQueryWrapper = new LambdaUpdateWrapper<A01Entity>();
			objectLambdaQueryWrapper.set(A01Entity::getStatus, ConstantDigit.A01_STATUS_CHECK);
			objectLambdaQueryWrapper.eq(A01Entity::getA0000, a01.getA0000());


			a01Service.update(objectLambdaQueryWrapper);
			s = "";
			A01Entity newObject = ObjectUtil.clone(a01);
			newObject.setStatus(ConstantDigit.A01_STATUS_CHECK);
			logManager.doBizUpdate(a01.getA0000(), LogManager.TYPE_A01, "审核", a01, newObject);

			// 如果存在散材料，更新散材料为状态为非散材料
			manageRsdamlService.updateSanCaiLiaoStatus(a01.getA0000());
		}
		return s;
	}

	@Override
	public String scanRefuse(A01Entity a01) {
		A01Entity oldObject = a01Service.getById(a01.getId());
		a01.setStatus(ConstantDigit.A01_STATUS_MENU);
		a01Service.saveOrUpdate(a01);
		logManager.doBizUpdate(a01.getA0000(), LogManager.TYPE_A01, "扫描驳回", oldObject, a01);
		return "";
	}

	@Override
	public String mlRefuse(A01Entity a01) {
		A01Entity oldData = a01Service.getById(a01.getId());
		a01.setStatus(ConstantDigit.A01_STATUS_ERCODE);
		a01Service.saveOrUpdate(a01);
		logManager.doBizUpdate(a01.getA0000(), LogManager.TYPE_A01, "目录驳回", oldData, a01);
		return "";
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public String checkMount(A01Entity a01) {
		String s = checkWj(a01, true);
		if (Func.isBlank(s)) {
			LambdaUpdateWrapper<A01Entity> objectLambdaQueryWrapper = new LambdaUpdateWrapper<A01Entity>();
			objectLambdaQueryWrapper.set(A01Entity::getStatus, ConstantDigit.A01_STATUS_HG);
			objectLambdaQueryWrapper.eq(A01Entity::getA0000, a01.getA0000());
			a01Service.update(objectLambdaQueryWrapper);

			A01Entity newObject = ObjectUtil.clone(a01);
			newObject.setStatus(ConstantDigit.A01_STATUS_HG);
			logManager.doBizUpdate(a01.getA0000(), LogManager.TYPE_A01, "挂载", a01, newObject);
		}
		return s;
	}


	@Transactional
	@Override
	public R<String> doImportDir(String filePath, String a0201b, boolean cover) {
		File file = FileUtil.file(filePath);
		String archiveName = file.getName();
		String dir = file.getPath();

		UserDaRs userDaRs = null;
		try {
			userDaRs = readXml(dir, archiveName);
		} catch (Exception e) {
			log.error("读取XML文件失败：" + e.getMessage(), e);
			return R.fail("读取XML文件失败：" + e.getMessage());
		}
		// 检查文件是否齐全
		String errors = checkErrorFiles(userDaRs, dir, cover);
		if (StringUtils.isNotBlank(errors)) {
			log.info("文件检查错误：" + errors);
			return R.fail("文件检查错误：" + errors);
		}
		// 读取人员基本信息
		UserInfoRs userInfo = userDaRs.getUserInfo();
		UmsUserInfoEntity userInfoEntity = saveUserInfo(userInfo, a0201b, cover);
		// 目录信息
		List<UserMenuRs> menus = userDaRs.getMenus();
		saveMenuRs(menus, userInfoEntity, dir, cover);
		logManager.doImport(userInfoEntity.getA0000(), LogManager.TYPE_A01, userInfoEntity);
		return R.success("");
	}

	@Override
	public Pair<Boolean, String> isFileUploaded(String fileHash) {
		String key = FILE_HASH_KEY_PREFIX + fileHash;
		boolean hashHas = redisTemplate.hasKey(key);
		if (hashHas) {
			String filePath = redisTemplate.opsForValue().get(key);
			if (FileUtil.exist(filePath)) {
				Pair.of(true, filePath);
			}
		}
		return Pair.of(false, null);
	}

	@Transactional
	@Override
	public R<String> doImportZip(MultipartFile multipartFile, String a0201b, boolean cover) {
		String filePathName;
		try {
			filePathName = unzipUploadFile(multipartFile);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return R.fail("文件解压失败：" + e.getMessage());
		}
		log.info("文件解压：{}", filePathName);
		return doImportDir(filePathName, a0201b, cover);
	}

	private String checkErrorFiles(UserDaRs userDaRs, String rootDir, boolean cover) {
		List<String> errors = Lists.newArrayList();
		String userName = userDaRs.getUserInfo().getUserName();
		String idCard = userDaRs.getUserInfo().getIdCard();
		if (!cover && StringUtils.isNotBlank(idCard)) {
			UmsUserInfoEntity one =
				getOne(Wrappers.<UmsUserInfoEntity>lambdaQuery().eq(UmsUserInfoEntity::getA0101, userName).eq(UmsUserInfoEntity::getA0184, idCard));
			if (Func.isNotEmpty(one)) {
				errors.add("相同姓名与身份证号的人员已存在");
			}
		}

		userDaRs.getMenus().stream().forEach(userMenuRs -> {
			for (int i = 0; i < userMenuRs.getPageNum(); i++) {
				if (i >= userMenuRs.getOrgImgs().size()) {
					errors.add("原始图像第" + (i + 1) + "页丢失");
					continue;
				}
				String orgImg = userMenuRs.getOrgImgs().get(i);
				String fullPathName = rootDir + File.separator + "图像数据" + File.separator + "原始图像数据" + File.separator + orgImg;
				File file = new File(fullPathName);
				if (FileUtil.exist(file) == false) {
					errors.add("原始图像" + orgImg + "丢失");
				}
			}
		});
		return errors.isEmpty() ? "" : String.join("，", errors);
	}

	private UmsUserInfoEntity saveUserInfo(UserInfoRs userInfo, String a0201b, boolean cover) {

		UmsUserInfoEntity a01ArchiveEntity = new UmsUserInfoEntity();

		// 如果允许覆盖，就尝试获取原始信息
		if (cover) {
			String userName = userInfo.getUserName();
			String idCard = userInfo.getIdCard();
			UmsUserInfoEntity one =
				getOne(Wrappers.<UmsUserInfoEntity>lambdaQuery().eq(UmsUserInfoEntity::getA0101, userName).eq(UmsUserInfoEntity::getA0184, idCard));
			if (one != null) {
				a01ArchiveEntity = one;
			}
		}

		// 姓名
		a01ArchiveEntity.setA0101(userInfo.getUserName());

		if (StringUtils.isNotBlank(userInfo.getSex())) {
			Dict sex = dictService.getOne(Wrappers.<Dict>lambdaQuery().eq(Dict::getCode, "sex").eq(Dict::getDictValue, userInfo.getSex()), true);
			if (sex != null) {
				// 性别
				a01ArchiveEntity.setA0104(sex.getDictKey());
			}
		}

		// 部门
		a01ArchiveEntity.setA0201b(a0201b);

		// 政治面貌
		if (StringUtils.isNotBlank(userInfo.getA0141())) {
			Dict GB4762 = dictService.getOne(Wrappers.<Dict>lambdaQuery().eq(Dict::getCode, "GB4762").eq(Dict::getDictValue, userInfo.getA0141()),
				true);
			if (GB4762 != null) {
				a01ArchiveEntity.setA0141(GB4762.getDictKey());
			}
		} else {
			a01ArchiveEntity.setA0141("01");
		}

		// 身份证号码
		a01ArchiveEntity.setA0184(userInfo.getIdCard());

		// 出生年月
		a01ArchiveEntity.setA0107(userInfo.getBirthDay());

		// 籍贯名称
		a01ArchiveEntity.setA0111a(userInfo.getA0111a());

		String mz = userInfo.getMz();
		if (StringUtils.isNotBlank(mz)) {
			if (mz.indexOf("族") == -1) {
				mz += "族";
			}
			// 民族
			Dict GB3304 = dictService.getOne(Wrappers.<Dict>lambdaQuery().eq(Dict::getCode, "GB3304").eq(Dict::getDictValue, mz), true);
			if (GB3304 != null) {
				a01ArchiveEntity.setA0117(GB3304.getDictKey());
			}
		}

		// 职务
		a01ArchiveEntity.setA0192(userInfo.getA0192());

		// TODO 职务层次
		a01ArchiveEntity.setA0221("01A99");

		// 人员状态, 暂存
		a01ArchiveEntity.setA01Status("01");

		// 已高清
		a01ArchiveEntity.setStatus(5);


		this.saveOneDa(a01ArchiveEntity);


		return a01ArchiveEntity;

	}


	@Autowired
	private IManageRsdamlService rsdamlService;

	@Autowired
	private IManageRsdawjService rsdawjService;

	private void saveMenuRs(List<UserMenuRs> menus, UmsUserInfoEntity userInfoEntity, String rootDir, boolean cover) {

		List<ManageRsdamlEntity> rsdamlEntities = org.apache.commons.compress.utils.Lists.newArrayList();
		List<ManageRsdawjEntity> rsdawjEntities = org.apache.commons.compress.utils.Lists.newArrayList();

		menus.stream().forEach(menu -> {
			ManageRsdamlEntity tmpentity = new ManageRsdamlEntity();
			tmpentity.setRsdaml002(menu.getClassNum());
			tmpentity.setClassSort(ConstantDigit.sortClassMap.get(menu.getClassNum()));
			tmpentity.setRsdaml003(NumberUtil.parseInt(menu.getIdNum()));
			tmpentity.setRsdaml004(menu.getCaiLiaoName());
			tmpentity.setRsdaml005(menu.getPageNum());

			Triple<String, String, String> date = ExcelExportUtil.getDate(menu.getCreateAtStr());
			tmpentity.setRsdaml006(date.getLeft());
			tmpentity.setRsdaml007(date.getMiddle());
			tmpentity.setRsdaml008(date.getRight());
			tmpentity.setRsdaml009(menu.getRemark());

			tmpentity.setArchiveId(userInfoEntity.getArchiveId());
			tmpentity.setA0000(userInfoEntity.getA0000());
			tmpentity.setRsdaml000(IdUtil.randomUUID());

			rsdawjEntities.addAll(handleWj(tmpentity, rootDir, menu));

			rsdamlEntities.add(tmpentity);
		});

		// TODO: 开启单独的事务
		rsdamlService.saveBatch(rsdamlEntities);
		rsdawjService.saveBatch(rsdawjEntities);
	}

	private List<ManageRsdawjEntity> handleWj(ManageRsdamlEntity tmpentity, String rootDir, UserMenuRs userMenuRs) {
		List<ManageRsdawjEntity> entities = Lists.newArrayList();

		for (int i = 0; i < userMenuRs.getPageNum(); i++) {
			if (i >= userMenuRs.getOrgImgs().size()) {
				break;
			}
			String orgImg = userMenuRs.getOrgImgs().get(i);
			String[] split = orgImg.split("-");
			String fileName = split[split.length - 1];
			String rsdawj001 = fileName.split("\\.")[0];

			String newFileName = IdUtil.randomUUID() + ".jpg";
			uploadSourceFiles(tmpentity.getA0000(), rootDir, "原始图像数据", "扫描图像数据", orgImg, newFileName);
			uploadSourceFiles(tmpentity.getA0000(), rootDir, "原始图像数据", "原始图像数据", orgImg, newFileName);

			if (userMenuRs.getHdImgs() != null) {
				String hdImg = ArrayUtil.get(userMenuRs.getHdImgs().toArray(), i);
				if (StringUtils.isNotBlank(hdImg)) {
					uploadSourceFiles(tmpentity.getA0000(), rootDir, "优化图像数据", "优化图像数据", hdImg, newFileName);
				}
			}

			ManageRsdawjEntity rsdawjEntity = new ManageRsdawjEntity();
			rsdawjEntity.setRsdawj000(tmpentity.getRsdaml000());
			rsdawjEntity.setRsdawj001(rsdawj001);
			rsdawjEntity.setRsdawj003(newFileName);
			rsdawjEntity.setRsdawj004(newFileName);
			rsdawjEntity.setA0000(tmpentity.getA0000());
			rsdawjEntity.setArchiveId(tmpentity.getArchiveId());
			rsdawjEntity.setSort(NumberUtil.parseInt(rsdawj001));
			entities.add(rsdawjEntity);
		}
		return entities;

	}

	private String uploadSourceFiles(String a0000, String rootDir, String sourceSubDir, String targetSubDir, String oldName, String newFileName) {
		String fullPathName = rootDir + File.separator + "图像数据" + File.separator + sourceSubDir + File.separator + oldName;
		File file = new File(fullPathName);
		if (FileUtil.exist(file)) {
			try (InputStream bufferedGbInputStream = Files.newInputStream(file.toPath())) {
				String uploadPathName = String.format("%s/图像数据/%s/%s", a0000, targetSubDir, newFileName);
				minioTemplate.uploadFileImage(bufferedGbInputStream, uploadPathName);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		return newFileName;
	}

	private static UserDaRs readXml(String dir, String archiveName) throws IOException {
		XmlMapper xmlMapper = new XmlMapper();
		xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		File file = new File(dir + File.separator + archiveName + ".xml");
		String sortedXmlContent = XmlNoteTool.getSortedXmlContent(file);
		log.info("从{}/{}获取到xml内容：{}", dir, archiveName, sortedXmlContent);
		UserDaRs daRs = xmlMapper.readValue(sortedXmlContent, UserDaRs.class);
		log.info("从{}/{}获取到json内容：{}", dir, archiveName, JSON.toJSONString(daRs));
		return daRs;
	}

	private String unzipUploadFile(MultipartFile multipartFile) throws IOException {
		//判断文件存在
		String parent = FileUtil.getParent(archiveConfiguration.getReceiveZipPath(), 0);
		if (!FileUtil.exist(parent)) {
			FileUtil.mkdir(parent);
		}
		String fileName = multipartFile.getOriginalFilename().replace(".zip", "");
		String filePathName =
			parent + File.separator + cn.hutool.core.date.DateUtil.format(new Date(), DatePattern.PURE_DATETIME_MS_PATTERN) + "_" + fileName;
		File destFile = new File(filePathName + ".zip");
		// 写入zip文件，并解压
		FileUtil.writeFromStream(multipartFile.getInputStream(), destFile, true);
		ZipUtil.unzip(destFile, CharsetUtil.CHARSET_GBK);
		return filePathName + File.separator + fileName;
	}


	private String checkWj(A01Entity a01, boolean isSort) {
		LambdaQueryWrapper<ManageRsdamlEntity> manageRsdamlEntityLambdaQueryWrapper =
			Wrappers.<ManageRsdamlEntity>lambdaQuery().eq(ManageRsdamlEntity::getA0000, a01.getA0000()).eq(ManageRsdamlEntity::getIsDeleted, 0)
				.orderByAsc(ManageRsdamlEntity::getClassSort).orderByAsc(ManageRsdamlEntity::getRsdaml003);
		List<ManageRsdamlEntity> list = manageRsdamlService.list(manageRsdamlEntityLambdaQueryWrapper);
		for (ManageRsdamlEntity rsdamlEntity : list) {
			List<ManageRsdawjEntity> listWj =
				manageRsdawjService.list(Wrappers.<ManageRsdawjEntity>lambdaQuery().eq(ManageRsdawjEntity::getRsdawj000,
					rsdamlEntity.getRsdaml000()).orderByAsc(ManageRsdawjEntity::getSort).orderByAsc(ManageRsdawjEntity::getCreateTime).eq(ManageRsdawjEntity::getIsDeleted, 0));
			if (Func.isEmpty(listWj) || listWj.size() < rsdamlEntity.getRsdaml005()) {
				return String.format("扫描图像未完成请扫描完成后再进行下一步操作:%s ,第 %s 份材料 %s ,%d / %d", rsdamlEntity.getRsdaml002(), rsdamlEntity.getRsdaml003(),
					rsdamlEntity.getRsdaml004(), listWj.size(), rsdamlEntity.getRsdaml005());
			} else {
				if (isSort) {
					List<Long> collect = listWj.stream().map(a -> a.getId()).collect(Collectors.toList());
					manageRsdawjService.updateSorts(collect);
				}
			}
		}
		return "";
	}


	@XmlRootElement(name = "root")
	public static class Root {

		private String name;

		private List<String> item1 = new ArrayList<>();

		private List<String> item2 = new ArrayList<>();

		@XmlElement(name = "name")
		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		@XmlTransient
		public List<String> getItem1() {
			return item1;
		}

		public void setItem1(List<String> item1) {
			this.item1 = item1;
		}

		@XmlTransient
		public List<String> getItem2() {
			return item2;
		}

		public void setItem2(List<String> item2) {
			this.item2 = item2;
		}

		@XmlElement(name = "item1")
		public void addItem1(String value) {
			this.item1.add(value);
		}

		@XmlElement(name = "item2")
		public void addItem2(String value) {
			this.item2.add(value);
		}
	}

	public static void main(String[] args) throws IOException, JAXBException {

		String filePath = "D:\\receiveDa\\receiveZippath\\20250215115322348_江玮（档案演示）370102197608221738\\江玮（档案演示）370102197608221738";
		File file = FileUtil.file(filePath);
		String archiveName = file.getName();
		String dir = file.getPath();
		System.out.println(archiveName);
		System.out.println(dir);

		int i = MurmurHash3.hash32x86(FileUtil.readBytes(new File("D:\\receiveDa\\receiveZippath\\20250215115322348_江玮（档案演示）370102197608221738" +
			".zip")));
		System.out.println(i);
	}


}
